#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>

#include <pthread.h>
#include <semaphore.h>

#include <signal.h>

int fds[4];
pthread_t ids[4];
sem_t sems[4];


void my_exit(int sig)
{
    for(int i = 0; i < 4; i++)
    {
        pthread_cancel(ids[i]);
        sem_destroy(sems + i);
    }
}

void *write_data(void *arg)
{
    int flag = 0;
    int num = *((int *)arg);

    char temp = 'A' + num;
    
    while (1)
    {
        sem_wait(&sems[num]);

        for (int i = 0; i < 4; i++)
        {
            if (flag != 0 || i <= num)
            {
                write(fds[i], &temp, 1);
            }
        }

        flag = 1;

        sem_post(&sems[(num + 1) % 4]);   
    }
}

void open_file()
{
    char temp[1] = "A";

    for (int i = 0; i < 4; i++)
    {
        temp[0] = 'A';
        temp[0] = temp[0] + i;
        if ((fds[i] = open(temp, O_RDWR | O_CREAT | O_TRUNC, 0655)) < 0)
        {
            perror("open file error!");
            exit(1);
        }
    }
}

void init_sems()
{
    for (int i = 0; i < 4; i++)
    {
        if (i == 0)
        {
            sem_init(sems + i, 0, 1);
        }
        else
        {
            sem_init(sems + i, 0, 0);
        }
    }
}

int main(int argc, char **argv)
{
    int ret;
    int nums[4] = {0,1,2,3};
    
    signal(SIGINT, my_exit);

    open_file();

    init_sems();
    
    for(int i = 0; i < 4; i++)
    {
        ret = pthread_create(ids + i, NULL, write_data, (void *)(nums + i));

        if(ret < 0)
        {
            perror("pthread create error!");
            exit(1);
        }

        pthread_detach(ids[i]);
    }

    pause();

    return 0;
}